Skip to content

feat: 일반 탐색 키워드 검색 구현#897

Merged
m6z1 merged 3 commits into
developfrom
feat/896
Jun 9, 2026
Merged

feat: 일반 탐색 키워드 검색 구현#897
m6z1 merged 3 commits into
developfrom
feat/896

Conversation

@m6z1

@m6z1 m6z1 commented Jun 6, 2026

Copy link
Copy Markdown
Member

📌𝘐𝘴𝘴𝘶𝘦𝘴

📎𝘞𝘰𝘳𝘬 𝘋𝘦𝘴𝘤𝘳𝘪𝘱𝘵𝘪𝘰𝘯

  • 일반 탐색 화면에 인기 키워드 검색 섹션을 추가했습니다.
  • /keywords/popular API를 연결하고, 키워드 칩 클릭 시 선택한 키워드 ID로 상세 탐색 결과 화면에 진입하도록 구현했습니다.
  • 검색 상태에서는 키워드 섹션을 숨기고, 검색창 X 버튼으로 초기 상태 복귀 시 다시 노출되도록 처리했습니다.

📷𝘚𝘤𝘳𝘦𝘦𝘯𝘴𝘩𝘰𝘵

default.mp4

💬𝘛𝘰 𝘙𝘦𝘷𝘪𝘦𝘸𝘦𝘳𝘴

  • git diff --check, ./gradlew ktlintCheck, ./gradlew :app:compileDebugKotlin 확인했습니다.

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능
    • 최근 검색어 목록 조회 및 개별/전체 삭제 기능 추가
    • 인기 키워드 표시 기능 추가
    • 장르별 검색 바로가기 추가
    • 키워드 검색 결과를 칩(Chip) 형태로 표시

@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown

Need an answer fast? Review this PR in Change Stack to ask focused questions about the PR or a changed range.

Review Change Stack

Warning

Review limit reached

@m6z1, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 58 minutes and 15 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b2f7a6ad-cb2d-4bc3-9859-f28df6246c0f

📥 Commits

Reviewing files that changed from the base of the PR and between c0a6e04 and fb9e9db.

📒 Files selected for processing (9)
  • app/src/main/java/com/into/websoso/data/mapper/KeywordMapper.kt
  • app/src/main/java/com/into/websoso/data/remote/api/KeywordApi.kt
  • app/src/main/java/com/into/websoso/data/remote/response/PopularKeywordsResponseDto.kt
  • app/src/main/java/com/into/websoso/data/repository/KeywordRepository.kt
  • app/src/main/java/com/into/websoso/ui/normalExplore/NormalExploreActivity.kt
  • app/src/main/java/com/into/websoso/ui/normalExplore/NormalExploreViewModel.kt
  • app/src/main/res/drawable/bg_normal_explore_keyword_search_chip.xml
  • app/src/main/res/layout/activity_normal_explore.xml
  • core/resource/src/main/res/values/strings.xml

Walkthrough

최근 검색 목록 조회·삭제 및 인기 키워드 검색 기능이 일반 탐색 화면에 추가되었습니다. API 엔드포인트에서 데이터를 수신하여 엔티티, UI 모델로 변환하고, RecyclerView 어댑터로 렌더링한 후 Activity에서 사용자 상호작용을 처리하는 전체 데이터 흐름이 구현되었습니다.

Changes

최근 검색 및 인기 키워드 탐색

Layer / File(s) Summary
Remote API 및 응답 DTO 계약
app/src/main/java/com/into/websoso/data/remote/api/KeywordApi.kt, app/src/main/java/com/into/websoso/data/remote/api/NovelApi.kt, app/src/main/java/com/into/websoso/data/remote/response/PopularKeywordsResponseDto.kt, app/src/main/java/com/into/websoso/data/remote/response/RecentSearchesResponseDto.kt
KeywordApi와 NovelApi에 인기 키워드 조회(getPopularKeywords), 최근 검색 조회/삭제(getRecentSearches, deleteRecentSearch, deleteAllRecentSearches) 엔드포인트를 추가하고, 응답 DTO를 정의하여 JSON 필드 매핑을 구성합니다.
엔티티 모델 및 데이터 매핑
app/src/main/java/com/into/websoso/data/model/RecentSearchesEntity.kt, app/src/main/java/com/into/websoso/data/mapper/KeywordMapper.kt, app/src/main/java/com/into/websoso/data/mapper/NovelMapper.kt
RecentSearchesEntity를 정의하고, PopularKeywordsResponseDto와 RecentSearchesResponseDto를 각각 KeywordEntity와 RecentSearchesEntity로 변환하는 확장 함수를 매퍼에 추가합니다.
리포지토리 계층
app/src/main/java/com/into/websoso/data/repository/KeywordRepository.kt, app/src/main/java/com/into/websoso/data/repository/NovelRepository.kt
KeywordRepository에 fetchPopularKeywords() 메서드를 추가하고, NovelRepository에 최근 검색 조회 및 삭제 메서드(fetchRecentSearches, deleteRecentSearch, deleteAllRecentSearches)를 추가합니다.
UI 모델 및 매퍼
app/src/main/java/com/into/websoso/ui/normalExplore/model/NormalExploreModel.kt, app/src/main/java/com/into/websoso/ui/normalExplore/model/GenreSearchModel.kt, app/src/main/java/com/into/websoso/ui/mapper/NovelMapper.kt
NormalExploreModel에 RecentSearchModel을 추가하고, GenreSearchModel과 장르-아이콘 매핑 리스트를 정의한 뒤, RecentSearchEntity를 RecentSearchModel로 변환하는 매퍼를 추가합니다.
ViewModel 상태 관리 및 로직
app/src/main/java/com/into/websoso/ui/normalExplore/NormalExploreViewModel.kt
KeywordRepository를 의존성 주입하고, 최근 검색·인기 키워드 목록 및 가시성 LiveData를 추가하며, 초기화 시 데이터를 조회하고 삭제 메서드와 가시성 업데이트 헬퍼를 구현합니다.
RecyclerView 어댑터
app/src/main/java/com/into/websoso/ui/normalExplore/adapter/RecentSearchAdapter.kt, app/src/main/java/com/into/websoso/ui/normalExplore/adapter/GenreSearchAdapter.kt
RecentSearchAdapter와 GenreSearchAdapter를 각각 구현하여 최근 검색(클릭/삭제 콜백)과 장르 검색(클릭 콜백) 항목을 바인딩하고, DiffUtil로 효율적인 업데이트를 처리합니다.
Activity 통합 및 상호작용
app/src/main/java/com/into/websoso/ui/normalExplore/NormalExploreActivity.kt
어댑터를 초기화하고 최근 검색·인기 키워드 LiveData를 옵저빙하여 UI 업데이트를 수행하며, 키워드/장르 칩을 동적 생성·스타일링하고, 클릭 시 상세 탐색 화면으로 이동하는 오버로드된 navigateToDetailExploreResult 메서드를 추가합니다.
UI 리소스 및 레이아웃 파일
app/src/main/res/drawable/bg_normal_explore_recent_search_chip.xml, app/src/main/res/drawable/ic_normal_explore_recent_search_delete.xml, app/src/main/res/layout/item_normal_explore_genre_search.xml, app/src/main/res/layout/item_normal_explore_recent_search.xml, app/src/main/res/layout/activity_normal_explore.xml, core/resource/src/main/res/values/strings.xml
최근 검색 칩 배경과 삭제 아이콘 drawable을 추가하고, 항목 레이아웃 두 개를 정의한 뒤, 메인 Activity 레이아웃에 최근 검색·장르 검색·키워드 검색 섹션을 추가하며, 관련 문자열 리소스 4개를 추가합니다.
DetailExploreResultViewModel 리팩터링
app/src/main/java/com/into/websoso/ui/detailExploreResult/DetailExploreResultViewModel.kt
별점 필터 적용 여부 판단 로직을 isRatingFilterApplied() 헬퍼 메서드로 추출하여 updateMessage()에서 재사용하도록 변경합니다.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Team-WSS/WSS-Android#874: 이전 PR과 NormalExploreViewModel, NormalExploreActivity의 검색 흐름 및 섹션 가시성 로직(updateSearchResult, updateSearchWordEmpty)에서 교차하므로 관련이 있습니다.

Suggested labels

🍯 [FEAT], [👸 공주 은영]

Suggested reviewers

  • s9hn
  • Sadturtleman

Poem

토끼가 뛰어들어 최근 검색들을 모으고,
인기 키워드 일곱을 반짝이게 정렬하니,
RecyclerView 어댑터들이 춤을 추네!
ViewModel의 LiveData 흐름 따라,
사용자는 찾는 것을 쉬이 찾도다. 🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목은 PR의 주요 변경 사항인 일반 탐색 화면의 키워드 검색 구현을 명확하고 간결하게 표현하고 있습니다.
Linked Issues check ✅ Passed PR의 모든 코드 변경 사항이 #896의 요구사항(7개 인기 키워드 표시, 키워드 클릭 시 상세 탐색 이동)을 충족합니다.
Out of Scope Changes check ✅ Passed PR에는 최근 검색 기능, 장르 검색 등의 기능도 포함되어 있으나, 이들은 키워드 검색 구현을 위한 필수적인 기반 작업으로 간주됩니다.
Description check ✅ Passed PR 설명이 필수 섹션을 모두 포함하고 있으며, 이슈 #896 해결, 인기 키워드 검색 섹션 추가 및 API 연결 구현을 명확히 설명합니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/896

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@m6z1 m6z1 added 🍯 [FEAT] 새로운 기능을 개발합니다. 🏹 궁사 명지 웹소소 공주의 은밀한 사냥생활 labels Jun 6, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/src/main/java/com/into/websoso/ui/normalExplore/NormalExploreViewModel.kt (1)

122-164: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

검색 초기화 후 이전 요청 응답이 UI를 다시 덮어쓸 수 있습니다.

Line 170-178에서 초기화해도, 이미 시작된 Line 131 코루틴이 나중에 성공하면 Line 137-150에서 _uiState가 다시 갱신됩니다. X 버튼으로 초기 상태로 돌아간 직후 이전 검색 결과가 재노출될 수 있습니다.

수정 예시
+import kotlinx.coroutines.Job
 import kotlinx.coroutines.launch
@@
 class NormalExploreViewModel
@@
     ) : ViewModel() {
+        private var searchJob: Job? = null
@@
         fun updateSearchResult(isSearchButtonClick: Boolean) {
@@
-            viewModelScope.launch {
+            val requestedWord = searchWord.value.orEmpty()
+            searchJob?.cancel()
+            searchJob = viewModelScope.launch {
                 _uiState.value = _uiState.value?.copy(loading = isSearchButtonClick)
                 runCatching {
-                    getNormalExploreResultUseCase(searchWord.value ?: "", isSearchButtonClick)
+                    getNormalExploreResultUseCase(requestedWord, isSearchButtonClick)
                 }.onSuccess { results ->
+                    if (requestedWord != searchWord.value.orEmpty()) return@onSuccess
                     if (results.novels.isNotEmpty()) {
@@
         fun updateSearchWordEmpty() {
+            searchJob?.cancel()
             _searchWord.value = ""
             savedStateHandle[SEARCH_AUTHOR] = ""
             _uiState.value = NormalExploreUiState()

Also applies to: 170-178

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@app/src/main/java/com/into/websoso/ui/normalExplore/NormalExploreViewModel.kt`
around lines 122 - 164, The search coroutine started in updateSearchResult can
finish after UI was reset and overwrite state; fix by making searches
cancellable and ensuring only the latest result updates UI: add a cancellable
reference (e.g., a private var currentSearchJob: Job?) in the ViewModel, cancel
currentSearchJob before launching the new viewModelScope.launch in
updateSearchResult, assign the launched Job to currentSearchJob, and optionally
check isActive or a captured request token (nonce) before applying the results
to _uiState and before calling fetchRecentSearchesInternal so stale responses
cannot overwrite the cleared/initial state.
🧹 Nitpick comments (1)
app/src/main/java/com/into/websoso/ui/normalExplore/NormalExploreViewModel.kt (1)

87-115: ⚡ Quick win

최근 검색/키워드 요청 실패가 무음으로 처리됩니다.

Line 94-113, Line 182-200에서 runCatchingonFailure가 없어 실패 시 UI 피드백/재시도 트리거가 없습니다. 최소한 에러 상태 노출(토스트/스낵바 이벤트 또는 로그) 처리를 추가하는 편이 안정적입니다.

Also applies to: 180-202

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@app/src/main/java/com/into/websoso/ui/normalExplore/NormalExploreViewModel.kt`
around lines 87 - 115, The runCatching calls in fetchRecentSearchesInternal
(invoked by fetchRecentSearches) and in fetchKeywordSearches swallow failures
because they lack onFailure handlers; add onFailure blocks to both so errors are
logged and the UI is notified (e.g., emit a single‑event LiveData/StateFlow like
_errorEvent or _snackbarEvent with a message and/or set an error state to enable
retry), and optionally trigger retry logic; ensure you reference the existing
symbols _recentSearches, updateRecentSearchesVisibility, _keywordSearches,
updateKeywordSearchesVisibility, and the functions fetchRecentSearchesInternal
and fetchKeywordSearches when wiring the error handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/main/java/com/into/websoso/data/mapper/KeywordMapper.kt`:
- Around line 12-13: The function PopularKeywordsResponseDto.toData currently
places the expression body on the next line causing a ktlint
standard:function-signature violation; fix it by moving the expression to the
same line as the function signature so the declaration reads as a single-line
expression body (e.g., adjust the toData function that returns
List<CategoriesEntity.CategoryEntity.KeywordEntity> so the "= keywords.map {
it.toData() }" is on the same line as the function signature).

In `@app/src/main/java/com/into/websoso/data/repository/KeywordRepository.kt`:
- Around line 15-16: 함수 fetchPopularKeywords의 expression-body 위치가 ktlint의
standard:function-signature 규칙을 위반하므로 빌드가 깨집니다; 함수 시그니처 끝난 직후에 '='와 구현을 같은 라인에
두지 말고 expression body 시작 위치를 규칙에 맞게 조정하여 '='을 시그니처 다음 줄로 옮기고 들여쓰기를 맞춰
keywordApi.getPopularKeywords().toData() 호출이 새 줄에서 올바르게 정렬되도록 수정하세요.

In `@app/src/main/res/layout/item_normal_explore_recent_search.xml`:
- Around line 34-41: The delete ImageView
(iv_normal_explore_recent_search_delete) lacks an accessibility label, so
TalkBack users can't know its purpose; update the layout or adapter to provide a
meaningful contentDescription (e.g., use a string resource like
R.string.accessibility_delete_recent_search) and ensure the view is announced as
actionable in RecentSearchAdapter where ivNormalExploreRecentSearchDelete is
wired (set contentDescription programmatically if dynamic, and confirm it
remains focusable/clickable for accessibility).

---

Outside diff comments:
In
`@app/src/main/java/com/into/websoso/ui/normalExplore/NormalExploreViewModel.kt`:
- Around line 122-164: The search coroutine started in updateSearchResult can
finish after UI was reset and overwrite state; fix by making searches
cancellable and ensuring only the latest result updates UI: add a cancellable
reference (e.g., a private var currentSearchJob: Job?) in the ViewModel, cancel
currentSearchJob before launching the new viewModelScope.launch in
updateSearchResult, assign the launched Job to currentSearchJob, and optionally
check isActive or a captured request token (nonce) before applying the results
to _uiState and before calling fetchRecentSearchesInternal so stale responses
cannot overwrite the cleared/initial state.

---

Nitpick comments:
In
`@app/src/main/java/com/into/websoso/ui/normalExplore/NormalExploreViewModel.kt`:
- Around line 87-115: The runCatching calls in fetchRecentSearchesInternal
(invoked by fetchRecentSearches) and in fetchKeywordSearches swallow failures
because they lack onFailure handlers; add onFailure blocks to both so errors are
logged and the UI is notified (e.g., emit a single‑event LiveData/StateFlow like
_errorEvent or _snackbarEvent with a message and/or set an error state to enable
retry), and optionally trigger retry logic; ensure you reference the existing
symbols _recentSearches, updateRecentSearchesVisibility, _keywordSearches,
updateKeywordSearchesVisibility, and the functions fetchRecentSearchesInternal
and fetchKeywordSearches when wiring the error handling.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 02838cbb-cc90-44a3-9a32-1ea9e7c664bf

📥 Commits

Reviewing files that changed from the base of the PR and between b2635e6 and c0a6e04.

📒 Files selected for processing (23)
  • app/src/main/java/com/into/websoso/data/mapper/KeywordMapper.kt
  • app/src/main/java/com/into/websoso/data/mapper/NovelMapper.kt
  • app/src/main/java/com/into/websoso/data/model/RecentSearchesEntity.kt
  • app/src/main/java/com/into/websoso/data/remote/api/KeywordApi.kt
  • app/src/main/java/com/into/websoso/data/remote/api/NovelApi.kt
  • app/src/main/java/com/into/websoso/data/remote/response/PopularKeywordsResponseDto.kt
  • app/src/main/java/com/into/websoso/data/remote/response/RecentSearchesResponseDto.kt
  • app/src/main/java/com/into/websoso/data/repository/KeywordRepository.kt
  • app/src/main/java/com/into/websoso/data/repository/NovelRepository.kt
  • app/src/main/java/com/into/websoso/ui/detailExploreResult/DetailExploreResultViewModel.kt
  • app/src/main/java/com/into/websoso/ui/mapper/NovelMapper.kt
  • app/src/main/java/com/into/websoso/ui/normalExplore/NormalExploreActivity.kt
  • app/src/main/java/com/into/websoso/ui/normalExplore/NormalExploreViewModel.kt
  • app/src/main/java/com/into/websoso/ui/normalExplore/adapter/GenreSearchAdapter.kt
  • app/src/main/java/com/into/websoso/ui/normalExplore/adapter/RecentSearchAdapter.kt
  • app/src/main/java/com/into/websoso/ui/normalExplore/model/GenreSearchModel.kt
  • app/src/main/java/com/into/websoso/ui/normalExplore/model/NormalExploreModel.kt
  • app/src/main/res/drawable/bg_normal_explore_recent_search_chip.xml
  • app/src/main/res/drawable/ic_normal_explore_recent_search_delete.xml
  • app/src/main/res/layout/activity_normal_explore.xml
  • app/src/main/res/layout/item_normal_explore_genre_search.xml
  • app/src/main/res/layout/item_normal_explore_recent_search.xml
  • core/resource/src/main/res/values/strings.xml

Comment thread app/src/main/java/com/into/websoso/data/mapper/KeywordMapper.kt Outdated
Comment on lines +15 to +16
suspend fun fetchPopularKeywords(): List<CategoriesEntity.CategoryEntity.KeywordEntity> =
keywordApi.getPopularKeywords().toData()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

추가된 메서드의 시그니처 포맷 때문에 빌드가 깨집니다.

Line 15의 함수 시그니처가 ktlint standard:function-signature 규칙을 위반해 CI가 실패합니다. 동일 규칙에 맞게 expression body 시작 위치를 조정해 주세요.

수정 예시
-        suspend fun fetchPopularKeywords(): List<CategoriesEntity.CategoryEntity.KeywordEntity> =
-            keywordApi.getPopularKeywords().toData()
+        suspend fun fetchPopularKeywords():
+            List<CategoriesEntity.CategoryEntity.KeywordEntity> = keywordApi.getPopularKeywords().toData()
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
suspend fun fetchPopularKeywords(): List<CategoriesEntity.CategoryEntity.KeywordEntity> =
keywordApi.getPopularKeywords().toData()
suspend fun fetchPopularKeywords():
List<CategoriesEntity.CategoryEntity.KeywordEntity> = keywordApi.getPopularKeywords().toData()
🧰 Tools
🪛 GitHub Actions: Android CI / 0_build.txt

[error] 15-15: ktlint error (standard:function-signature): First line of body expression fits on same line as function signature (standard:function-signature)

🪛 GitHub Actions: Android CI / build

[error] 15-15: ktlint (standard:function-signature): First line of body expression fits on same line as function signature.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/java/com/into/websoso/data/repository/KeywordRepository.kt`
around lines 15 - 16, 함수 fetchPopularKeywords의 expression-body 위치가 ktlint의
standard:function-signature 규칙을 위반하므로 빌드가 깨집니다; 함수 시그니처 끝난 직후에 '='와 구현을 같은 라인에
두지 말고 expression body 시작 위치를 규칙에 맞게 조정하여 '='을 시그니처 다음 줄로 옮기고 들여쓰기를 맞춰
keywordApi.getPopularKeywords().toData() 호출이 새 줄에서 올바르게 정렬되도록 수정하세요.

Source: Pipeline failures

Comment on lines +34 to +41
<ImageView
android:id="@+id/iv_normal_explore_recent_search_delete"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginStart="6dp"
android:contentDescription="@null"
android:padding="4dp"
android:src="@drawable/ic_normal_explore_recent_search_delete" />

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

삭제 아이콘의 접근성 레이블이 누락되었습니다.

RecentSearchAdapter에서 ivNormalExploreRecentSearchDelete에 클릭 리스너를 직접 연결하고 있는데, 현재 contentDescription="@null"이라 TalkBack 사용자는 이 버튼의 의미를 알 수 없습니다.

수정 제안
--- a/app/src/main/res/layout/item_normal_explore_recent_search.xml
+++ b/app/src/main/res/layout/item_normal_explore_recent_search.xml
@@
         <ImageView
             android:id="@+id/iv_normal_explore_recent_search_delete"
             android:layout_width="16dp"
             android:layout_height="16dp"
             android:layout_marginStart="6dp"
-            android:contentDescription="`@null`"
+            android:contentDescription="`@string/normal_explore_recent_search_delete`"
             android:padding="4dp"
             android:src="`@drawable/ic_normal_explore_recent_search_delete`" />
--- a/core/resource/src/main/res/values/strings.xml
+++ b/core/resource/src/main/res/values/strings.xml
@@
     <string name="normal_explore_recent_search_delete_all">전체삭제</string>
+    <string name="normal_explore_recent_search_delete">최근 검색어 삭제</string>
     <string name="normal_explore_genre_search_title">장르별 검색</string>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<ImageView
android:id="@+id/iv_normal_explore_recent_search_delete"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginStart="6dp"
android:contentDescription="@null"
android:padding="4dp"
android:src="@drawable/ic_normal_explore_recent_search_delete" />
<ImageView
android:id="@+id/iv_normal_explore_recent_search_delete"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginStart="6dp"
android:contentDescription="`@string/normal_explore_recent_search_delete`"
android:padding="4dp"
android:src="`@drawable/ic_normal_explore_recent_search_delete`" />
Suggested change
<ImageView
android:id="@+id/iv_normal_explore_recent_search_delete"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginStart="6dp"
android:contentDescription="@null"
android:padding="4dp"
android:src="@drawable/ic_normal_explore_recent_search_delete" />
<string name="normal_explore_recent_search_delete_all">전체삭제</string>
<string name="normal_explore_recent_search_delete">최근 검색어 삭제</string>
<string name="normal_explore_genre_search_title">장르별 검색</string>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/res/layout/item_normal_explore_recent_search.xml` around lines
34 - 41, The delete ImageView (iv_normal_explore_recent_search_delete) lacks an
accessibility label, so TalkBack users can't know its purpose; update the layout
or adapter to provide a meaningful contentDescription (e.g., use a string
resource like R.string.accessibility_delete_recent_search) and ensure the view
is announced as actionable in RecentSearchAdapter where
ivNormalExploreRecentSearchDelete is wired (set contentDescription
programmatically if dynamic, and confirm it remains focusable/clickable for
accessibility).

@Sadturtleman Sadturtleman left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고하셨습니다!

@devfeijoa devfeijoa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고하셨습니다 뭉치! 👍🏻

@m6z1 m6z1 merged commit 081109e into develop Jun 9, 2026
1 of 2 checks passed
@m6z1 m6z1 deleted the feat/896 branch June 9, 2026 13:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🍯 [FEAT] 새로운 기능을 개발합니다. 🏹 궁사 명지 웹소소 공주의 은밀한 사냥생활

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: 일반 탐색 키워드 검색 구현

3 participants